package cn.xsshome.imagetool.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * @author 小帅丶
 * @Description Java模拟双重曝光对图片进行处理
 *              图片双重曝光Java实现
 *              两张图片一定要宽高一致
 * @date 2024/1/10
 */
public class DoubleExposureUtil {

    //默认透明度
    private static float alpha = 0.5f;

    /**
     * @Description  模拟双重曝光
     * @param firstPath - 第一张图片
     * @param secondPath  - 第二张图片
     * @Date  2024/1/10
     * @Author 小帅丶
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage doubleExposure(String firstPath, String secondPath) throws Exception {
       return doubleExposure(firstPath,secondPath,alpha);
    }

    /**
     * @Description  模拟双重曝光
     * @param firstPath - 第一张图片
     * @param secondPath  - 第二张图片
     * @param alpha - 透明度
     * @Date  2024/1/10
     * @Author 小帅丶
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage doubleExposure(String firstPath, String secondPath, float alpha) throws Exception {
        return doubleExposure(firstPath,secondPath,alpha,alpha);
    }

    /**
     * @Description  模拟双重曝光
     * @param firstPath - 第一张图片
     * @param secondPath  - 第二张图片
     * @param firstAlpha - 第一张图透明度
     * @param secondAlpha - 第二张图透明度
     * @Date  2024/1/10
     * @Author 小帅丶
     * @return java.awt.image.BufferedImage
     **/
    public static BufferedImage doubleExposure(String firstPath, String secondPath,
                                               float firstAlpha, float secondAlpha) throws Exception {
        // 读取第一张图片
        BufferedImage image1 = ImageIO.read(new File(firstPath));
        // 读取第二张图片
        BufferedImage image2 = ImageIO.read(new File(secondPath));
        if (image1.getWidth() == image2.getWidth() && image1.getHeight() == image2.getHeight()) {
            // 将两张图片合并成一张
            BufferedImage combinedImage = new BufferedImage(image1.getWidth(), image1.getHeight(),
                    BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = combinedImage.createGraphics();
            g2d.drawImage(image1, 0, 0, null);
            g2d.setComposite(AlphaComposite.SrcOver.derive(firstAlpha));
            g2d.drawImage(image2, 0, 0, null);
            g2d.setComposite(AlphaComposite.SrcOver.derive(secondAlpha));
            g2d.dispose();
            // 实现双重曝光效果
            BufferedImage doubleExposureImage = new BufferedImage(image1.getWidth(), image1.getHeight(),
                    BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2dExposure = doubleExposureImage.createGraphics();
            g2dExposure.drawImage(combinedImage, 0, 0, null);
            g2dExposure.dispose();
            return doubleExposureImage;
        }
        return null;
    }

    /**
     * @Description  模拟双重曝光-需要引入javacv-platform
     *        <dependency>
     *             <groupId>org.bytedeco</groupId>
     *             <artifactId>javacv-platform</artifactId>
     *             <version>1.5.7</version>
     *         </dependency>
     * @param openCVdllPath - opencvdll文件路径
     * @param firstPath - 第一张图片
     * @param secondPath  - 第二张图片
     * @param firstAlpha - 第一张图透明度
     * @param secondAlpha - 第二张图透明度
     * @Date  2024/1/10
     * @Author 小帅丶
     * @return java.awt.image.BufferedImage
     **/
    /******************* openCV Mat 双重曝光
    public static BufferedImage doubleExposureByOpenCV(String openCVdllPath,
                                                       String firstPath, String secondPath,
                                                       float firstAlpha, float secondAlpha) throws Exception {
        //加载dll文件
        System.load(openCVdllPath);
        // 加载本地图像文件
        Mat image1 = Imgcodecs.imread(firstPath);
        Mat image2 = Imgcodecs.imread(secondPath);

        if (image1.empty() || image2.empty()) {
            System.out.println("无法读取图像文件！");
            return null;
        }
        // 创建输出结果图像对象
        Mat resultImage = new Mat();
        // 将两张图像进行相加操作
        Core.addWeighted(image1, firstAlpha, image2, secondAlpha, 0, resultImage);
        // 保存结果图像到本地
        Imgcodecs.imwrite("result_image.jpg", resultImage);
        //Mat转BufferedImage bufferedImage保存最好是png格式 未深究 如果保存jpg会变红
        BufferedImage bufferedImage = matToBufferedImage(resultImage);
        // 释放内存
        image1.release();
        image2.release();
        resultImage.release();
        return bufferedImage;
    }
     *******************/

    /**
     * @Description Mat转BufferedImage
     * @param mat - Mat对象
     * @Author 小帅丶
     * @Date  2024/1/12
     * @return java.awt.image.BufferedImage
     **/
    /******************* openCV Mat转BufferedImage
    public static BufferedImage matToBufferedImage(Mat mat) {
        // 获取图像的宽度和高度
        int width = mat.cols();
        int height = mat.rows();
        // 创建一个空的BufferedImage，具有与Mat相同的宽度和高度，以及与Mat相同的深度和类型
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        // 将Mat的像素数据复制到BufferedImage中
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 假设图像是灰度图，获取像素值（如果是彩色图，需要相应地修改）
                // int pixel = (int)mat.get(y, x)[0];
                int b = (int)mat.get(y, x)[0];
                int g = (int)mat.get(y, x)[1];
                int r = (int)mat.get(y, x)[2];
                // 将像素值设置为颜色值
                bufferedImage.setRGB(x, y, new Color(r,g,b).getRGB());
            }
        }
        return bufferedImage;
    }
    *******************/
}
